﻿namespace DistrRTgen
{
    using rtgen_worker;
    using System;
    using System.Threading;

    internal class HashIndexerThread : WorkThread
    {
        private UpdateCrackingProgressCallback _Callback;
        private float _Progress;
        private Thread _Thread;
        public EventHandler _ThreadExited;
        private IndexHash _Work;

        public HashIndexerThread(IndexHash Work, EventHandler ThreadExited)
        {
            this._Work = Work;
            this._Thread = new Thread(new System.Threading.ThreadStart(this.ThreadStart));
            this._Callback = new UpdateCrackingProgressCallback(this.ThreadCallback);
            this._ThreadExited = ThreadExited;
        }

        public override void Start()
        {
            this._Thread.Start();
            this._Thread.Priority = ThreadPriority.Lowest;
        }

        public override void Stop()
        {
            this._Thread.Abort();
        }

        private void ThreadCallback(int RequestID, float fProgress)
        {
            this._Progress = fProgress;
        }

        private void ThreadStart()
        {
            try
            {
                Logger.AddLogLine("Starting HashIndexer for RequestID " + this._Work.RequestID, LoggerLevel.LOG_DEBUG);
                if (this._Work == null)
                {
                    Logger.AddLogLine("HashIndexer started with no work! Quitting", LoggerLevel.LOG_DEBUG);
                }
                else
                {
                    RainbowCrack rc = new RainbowCrack();
                    ulong[] Indices = new ulong[this._Work.ChainLength - 1];
                    switch (RainbowCrack.CalculateIndexList(Indices, this._Work.Hash, this._Work.HashRoutine, this._Work.Charset, this._Work.MinLetters, this._Work.MaxLetters, this._Work.Index, this._Work.ChainLength, this._Work.RequestID, this._Callback))
                    {
                        case 1:
                            Logger.AddLogLine("Hash Indexer returned with error code 1: Hashroutine " + this._Work.HashRoutine + " not supported", LoggerLevel.LOG_ALERT);
                            break;

                        case 2:
                            Logger.AddLogLine("Hash Indexer returned with error code 2: Charset " + this._Work.Charset + " not found", LoggerLevel.LOG_ALERT);
                            break;

                        case 3:
                            Logger.AddLogLine("Hash Indexer returned with error code 3: Rainbow table index " + this._Work.Index + " is invalid", LoggerLevel.LOG_ALERT);
                            break;

                        case 0:
                            this._Work.IndexListUint64 = Indices;
                            break;
                    }
                    Logger.AddLogLine("HashIndexer for RequestID " + this._Work.RequestID + " completed successfully", LoggerLevel.LOG_DEBUG);
                    this._ThreadExited(this, null);
                }
            }
            catch (ThreadAbortException)
            {
            }
        }

        public IndexHash Work
        {
            get
            {
                return this._Work;
            }
        }
    }
}

